﻿' Copyright (c) Måns Björkman 1998-2010

' Ported from VB6 and adapted as a Transcriber plug-in by Kirk Rader

' $Header: $

' $History: $

Imports System.Windows.Forms
Imports Transcriber.Api
Imports System.IO

<Assembly: TranscriberPluginAssembly()> 

''' <summary>
''' <see cref="ITranscriberPlugin"/> that uses mode
''' files compatible with Måns Björkman's
''' TengScribe application.
''' </summary>
Public Class ModeFileTranscriber

    Inherits TranscriberPlugin

    ''' <summary>
    ''' Gets the mode file directory.
    ''' </summary>
    ''' <value>The mode directory.</value>
    Public ReadOnly Property ModeDirectory() As String

        Get
            Return Me.mModeDirectory.FullName
        End Get

    End Property

    ''' <summary>
    ''' Gets or sets the current mode.
    ''' </summary>
    ''' <value>The current mode.</value>
    Public Property CurrentMode() As String
        Get
            Return Me.strCurrentMode
        End Get

        Set(ByVal value As String)
            Me.strCurrentMode = value
        End Set

    End Property

    ''' <summary>
    ''' Gets the name of this plug-in object.
    ''' </summary>
    ''' <value>The name.</value>
    Public Overrides ReadOnly Property Name() As String

        Get
            Return "Mode File Transcriber"
        End Get

    End Property

    ''' <summary>
    ''' Initializes a new instance of the <see cref="ModeFileTranscriber" /> class.
    ''' </summary>
    Public Sub New(ByVal Transcriber As ITranscriberApplication)

        MyBase.New(Transcriber)

        Me.mModeDirectory = New DirectoryInfo(AppDomain.CurrentDomain.SetupInformation.ApplicationBase + "Modes\")
        Me.CurrentMode = My.Settings.ModeFile

    End Sub

    ''' <summary>
    ''' Transcribes the specified text.
    ''' </summary>
    ''' <param name="Text">The text.</param>
    ''' <returns></returns>
    Public Overrides Function Transcribe(ByVal Text As String) As String

        Transcribe = Me.GenerateCharacters(Text)

    End Function

    ''' <summary>
    ''' Gets the settings dialog.
    ''' </summary>
    ''' <returns>The settings dialog.</returns>
    Public Overrides Function GetSettingsDialog() As Form

        GetSettingsDialog = New frmModeFileTranscriberSettings(Me)

    End Function

    Protected Overrides Sub Terminate()
        My.Settings.Save()
        MyBase.Terminate()
    End Sub

    Public Overrides Function GetDestinationContextMenuItems() As System.Windows.Forms.ToolStripItem()

        Dim items(0 To 3) As ToolStripItem

        items(0) = New ToolStripButton("Standard Lines to Curled", Nothing, New EventHandler(AddressOf mnuStandardLinesToCurled))
        items(1) = New ToolStripButton("Curled Lines to Standard", Nothing, New EventHandler(AddressOf mnuCurledLinesToStandard))
        items(2) = New ToolStripButton("Standard S-curl to Looped", Nothing, New EventHandler(AddressOf mnuStandardScurlToLooped))
        items(3) = New ToolStripButton("Looped S-curl to Standard", Nothing, New EventHandler(AddressOf mnuLoopedScurlToStandard))

        GetDestinationContextMenuItems = items

    End Function

    Private Sub mnuStandardLinesToCurled(ByVal Sender As Object, ByVal Args As EventArgs)
        MessageBox.Show(String.Format("Not yet implemented ({0})", Me.Transcriber.DestinationText), "Standard Lines to Curled")
    End Sub

    Private Sub mnuCurledLinesToStandard(ByVal Sender As Object, ByVal Args As EventArgs)
        MessageBox.Show(String.Format("Not yet implemented ({0})", Me.Transcriber.DestinationText), "Curled Lines to Standard")
    End Sub

    Private Sub mnuStandardScurlToLooped(ByVal Sender As Object, ByVal Args As EventArgs)
        MessageBox.Show(String.Format("Not yet implemented ({0})", Me.Transcriber.DestinationText), "Standard S-curl to Looped")
    End Sub

    Private Sub mnuLoopedScurlToStandard(ByVal Sender As Object, ByVal Args As EventArgs)
        MessageBox.Show(String.Format("Not yet implemented ({0})", Me.Transcriber.DestinationText), "Looped S-curl to Standard")
    End Sub

    Private Const ENTMAX As Short = 16

    Private dblStatusPercent As Double
    Private boolCancelGeneration As Boolean

    Private intCaseSensitive As Short
    Private strModeComment As String
    Private strModeText() As String
    Private strModeTranscription() As String
    Private strModeNext() As String
    Private strModePreviousTengwa() As String
    Private strModeThisTengwa() As String
    Private strUndefinedTranscribe As String
    Private mModeDirectory As DirectoryInfo
    Private strCurrentMode As String
    Private boolUndefinedAlert As Boolean

    Private Function GenerateCharacters(ByRef strText As String) As String

        Dim lngCharacterPos As Integer 'Håller reda på aktuell teckenposition.
        Dim intTextLength As Short 'Textens längd.
        Dim intEntityLength As Short 'Håller reda på längden på aktuell entitet.
        Dim strEntityText As String 'Innehåller texten i aktuell entitet.
        Dim strNextChar As String 'Innehåller nästa tecken efter entiteten.
        Dim intEntMax As Short 'Maxlängden på en entitet.
        Dim strEntPreviousTengwa As String = "" 'Föregående tengwa
        Dim R As Short 'Generell räknare.
        Dim boolPreviousMatch As Boolean
        Dim boolNextMatch As Boolean
        Dim boolUndefinedChars As Boolean

        intTextLength = Len(strText)

        If intTextLength < ENTMAX Then
            intEntMax = intTextLength
        Else
            intEntMax = ENTMAX
        End If
        lngCharacterPos = 1

        strText = MaskCase(strText)

        GenerateCharacters = ""

        Do While lngCharacterPos <= intTextLength 'Loopa tills teckenpositionen = slutet på texten.
            dblStatusPercent = lngCharacterPos / intTextLength
            If boolCancelGeneration = True Then
                Exit Function
            End If
            For intEntityLength = intEntMax To 1 Step -1 'Loopa medan alla möjliga entitetslängder gås igenom.
                strEntityText = Mid(strText, lngCharacterPos, intEntityLength)
                strNextChar = Mid(strText, lngCharacterPos + intEntityLength, 1)
                If intEntityLength = 1 And Asc(strEntityText) < 32 Then
                    GenerateCharacters = GenerateCharacters + strEntityText
                    strEntPreviousTengwa = strEntityText
                    R = -255
                Else
                    For R = 0 To UBound(strModeText) 'Kollar entiteten mot det aktuella modet.

                        boolPreviousMatch = False
                        boolNextMatch = False
                        If strModePreviousTengwa(R) <> "" Then
                            If Asc(strModePreviousTengwa(R)) = 13 Then 'Om föregående tecken stämmer.
                                If strEntPreviousTengwa = "" Then
                                    boolPreviousMatch = True
                                Else
                                    If Asc(strEntPreviousTengwa) < 33 Then
                                        boolPreviousMatch = True
                                    End If
                                End If
                            End If
                        End If
                        If strModePreviousTengwa(R) = strEntPreviousTengwa Or strModePreviousTengwa(R) = "" Then 'Om föregående tecken stämmer.
                            boolPreviousMatch = True
                        End If

                        If strModeNext(R) <> "" Then
                            If Asc(strModeNext(R)) = 13 Then 'Om nästa tecken stämmer.
                                If strNextChar = "" Then
                                    boolNextMatch = True
                                Else
                                    If Asc(strNextChar) < 48 Then
                                        boolNextMatch = True
                                    End If
                                End If
                            End If
                        End If
                        If strModeNext(R) = strNextChar Or strModeNext(R) = "" Then 'Om nästa tecken stämmer.
                            boolNextMatch = True
                        End If

                        If boolPreviousMatch = True And boolNextMatch = True Then
                            If strModeText(R) = strEntityText Then
                                GenerateCharacters = GenerateCharacters + CStr(strModeTranscription(R))
                                strEntPreviousTengwa = CStr(strModeThisTengwa(R))
                                R = -255
                                Exit For
                            End If
                        End If
                    Next R
                End If
                If R = -255 Then 'Om en text har genererats.
                    lngCharacterPos = lngCharacterPos + intEntityLength 'Teckenpositionen flyttas fram till nästa obearbetade tecken.
                    Exit For
                End If
            Next intEntityLength

            If R <> -255 Then
                GenerateCharacters = GenerateCharacters + strUndefinedTranscribe
                strEntPreviousTengwa = ""
                lngCharacterPos = lngCharacterPos + 1
                boolUndefinedChars = True
            End If
            System.Windows.Forms.Application.DoEvents()
        Loop

        If boolUndefinedChars = True And boolUndefinedAlert = True Then
            MsgBox("Some of the characters were not defined in the selected mode. These could not be transcribed.", MsgBoxStyle.Exclamation, "Warning")
        End If

    End Function

    Sub LoadMode()

        Dim buffer(35) As Byte
        Dim strModePost As String
        Dim modeFile As FileInfo
        Dim intCurTab As Short = 1
        Dim intLastTab As Short
        Dim AdressCount As Integer = 1
        Dim ArrayCount As Integer = 1

        ReDim strModeText(ArrayCount + 1)
        ReDim strModeTranscription(ArrayCount + 1)
        ReDim strModeNext(ArrayCount + 1)
        ReDim strModePreviousTengwa(ArrayCount + 1)
        ReDim strModeThisTengwa(ArrayCount + 1)

        modeFile = New FileInfo(Me.mModeDirectory.FullName + strCurrentMode + ".mod")

        If Not modeFile.Exists Then Throw New InvalidOperationException("No file found named " + modeFile.FullName)

        Using modeStream As Stream = modeFile.OpenRead()

            If buffer.Length <> modeStream.Read(buffer, 0, buffer.Length) Then Throw New InvalidOperationException("Unexpected end of file reading " + modeFile.FullName)

            strModePost = New String(Encoding.UTF7.GetChars(buffer))

            intCurTab = InStr(strModePost, vbTab)
            strModeComment = Left(strModePost, intCurTab - 1)

            intCaseSensitive = CShort(Mid(strModePost, intCurTab + 1, 1))

            AdressCount = AdressCount + 1

            Do While buffer.Length = modeStream.Read(buffer, 0, buffer.Length)
                ReDim Preserve strModeText(ArrayCount + 1)
                ReDim Preserve strModeTranscription(ArrayCount + 1)
                ReDim Preserve strModeNext(ArrayCount + 1)
                ReDim Preserve strModePreviousTengwa(ArrayCount + 1)
                ReDim Preserve strModeThisTengwa(ArrayCount + 1)

                strModePost = New String(Encoding.UTF7.GetChars(buffer))

                If Asc(strModePost) > 9 Then
                    intCurTab = InStr(strModePost, vbTab)
                    strModeText(ArrayCount) = Mid(strModePost, 1, intCurTab - 1)
                    intLastTab = intCurTab
                    intCurTab = InStr(intLastTab + 1, strModePost, vbTab)
                    strModeTranscription(ArrayCount) = Mid(strModePost, intLastTab + 1, intCurTab - (intLastTab + 1))
                    intLastTab = intCurTab
                    intCurTab = InStr(intLastTab + 1, strModePost, vbTab)
                    strModeNext(ArrayCount) = Mid(strModePost, intLastTab + 1, intCurTab - (intLastTab + 1))
                    intLastTab = intCurTab
                    intCurTab = InStr(intLastTab + 1, strModePost, vbTab)
                    strModePreviousTengwa(ArrayCount) = Mid(strModePost, intLastTab + 1, intCurTab - (intLastTab + 1))
                    intLastTab = intCurTab
                    intCurTab = InStr(intLastTab + 1, strModePost, vbTab)
                    strModeThisTengwa(ArrayCount) = Mid(strModePost, intLastTab + 1, intCurTab - (intLastTab + 1))

                    ArrayCount = ArrayCount + 1
                End If

                AdressCount = AdressCount + 1

            Loop

        End Using

    End Sub


    Function MaskCase(ByVal strText As String) As String

        Select Case intCaseSensitive

            Case 0
                MaskCase = LCase(strText)

            Case Else
                MaskCase = strText

        End Select

    End Function

End Class